package com.skyline.energy.definition;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.ClassUtils;

import com.skyline.energy.annotation.BatchUpdate;
import com.skyline.energy.annotation.ReturnId;
import com.skyline.energy.exception.DaoGenerateException;
import com.skyline.energy.utils.CommonUtils;

public class JdbcBatchUpdateDefinition extends BaseJdbcDefinition {
	private boolean isReturnId = false;
	private boolean isReturnList = false;
	private Class<?> returnComponentType;

	public boolean isReturnId() {
		return isReturnId;
	}

	public boolean isReturnList() {
		return isReturnList;
	}

	public Class<?> getReturnComponentType() {
		return returnComponentType;
	}

	public JdbcBatchUpdateDefinition(Method method) throws DaoGenerateException {
		init(method);
	}

	private void init(Method method) throws DaoGenerateException {
		checkReturnType(method);

		Map<String, Integer> paramIndexes = new HashMap<String, Integer>(8, 1f);
		Map<String, Integer> batchParamIndexes = new HashMap<String, Integer>(8, 1f);
		Class<?>[] paramTypes = method.getParameterTypes();
		Annotation[][] annotations = method.getParameterAnnotations();
		parseParameterAnnotations(annotations, paramIndexes, batchParamIndexes, paramTypes);

		BatchUpdate update = method.getAnnotation(BatchUpdate.class);
		parseSql(update.value(), paramTypes, paramIndexes, batchParamIndexes);
		
		parseShardBy(method, paramIndexes, paramTypes);
	}

	private void checkReturnType(Method method) throws DaoGenerateException {
		isReturnId = (method.getAnnotation(ReturnId.class) != null);

		Class<?> returnType = method.getReturnType();
		if (isReturnId && returnType != null) {
			if (CommonUtils.isTypeList(returnType)) {
				isReturnList = true;
			} else if (!CommonUtils.isTypeArray(returnType)) {
				throw new DaoGenerateException("@ReturnId must on a method return List<? extends Number> or an array");
			} else {
				returnComponentType = returnType.getComponentType();
				if (!ClassUtils.isAssignable(returnComponentType, Number.class, true)) {
					throw new DaoGenerateException(
							"@ReturnId return an array that only can be primitive or assignable to Number");
				}

				isReturnList = false;
			}
		} else {
			if (void.class.equals(returnType) || int.class.equals(returnType.getComponentType())) {
				return;
			}
			throw new DaoGenerateException("@BatchUpdate must on a method return void or int[]");
		}
	}
}
